﻿using SuperMap.Data;
using SuperMap.Realspace;
using SuperMap.UI;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
using Ycjw.PipeLine.Map.Basic.SuperMap;

namespace Ycjw.PipeLine.Map.Tools.Conditions.ProfileAnalyst
{
    public class SceneProfileAnalyst : SceneOperInterface
    {

        public override void UnRegister()
        {
            m_SceneControl.Tracked -= SceneControl_Tracked;
            m_SceneControl.Tracking -= SceneControl_Tracking;
            base.UnRegister();
        }
        GeoLine3D m_TheLine;
        /// <summary>
        /// 初始化控件和数据
        /// Initialize the control and data
        /// </summary>
        public SceneProfileAnalyst(SceneControl sceneControl, Form formMain) : base(sceneControl, formMain)
        {
            m_SceneControl = sceneControl;

        }

        DatasetGrid GetDatasetGrid()
        {
            DatasetGrid result = null;
            foreach (TerrainLayer lyr in m_SceneControl.Scene.TerrainLayers)
            {
                if (lyr.Dataset is DatasetGrid)
                {
                    result = lyr.Dataset as DatasetGrid;
                    break;
                }
            }
            return result;
        }


        /// <summary>
        /// 打开工作空间，并加载数据到场景；注册事件
        /// Open the workspace and add the data to the scene. Register the event
        /// </summary>
        private void Initialize()
        {
            try
            {
                m_TheLine = null;
                m_SceneControl.Tracked -= SceneControl_Tracked;
                m_SceneControl.Tracking -= SceneControl_Tracking;


                m_SceneControl.Tracked += SceneControl_Tracked;
                m_SceneControl.Tracking += SceneControl_Tracking;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        private void SceneControl_Tracking(object sender, Tracking3DEventArgs e)
        {
            if (Action3D.CreateLine != this.m_SceneControl.Action) return;
            var tag = "cycle_tmp";
            var index = m_SceneControl.Scene.TrackingLayer.IndexOf(tag);
            if (index > -1)
            {
                m_SceneControl.Scene.TrackingLayer.Remove(index);
            }
            if (!(e.Geometry is GeoLine3D line3d) || line3d.Length == 0)
            {
                return;
            }
            m_SceneControl.Scene.TrackingLayer.Add(line3d, tag);
        }
        private void SceneControl_Tracked(object sender, Tracked3DEventArgs e)
        {
            var geom = e.Geometry;
            if (geom == null) return;
            if (geom.Type == SuperMap.Data.GeometryType.GeoLine3D)
            {
                m_TheLine = geom as GeoLine3D;
                var tag = "cycle_tmp";
                geom.Style3D = new GeoStyle3D()
                {
                    LineColor = Color.Yellow,
                    LineWidth = 4
                };
                m_SceneControl.Scene.TrackingLayer.Add(geom, tag);
            }
        }

        /// <summary>
        /// 开始绘制
        /// Start drawing
        /// </summary>
        public void StartDraw()
        {
            try
            {
                this.m_SceneControl.Action = Action3D.CreateLine;
                Initialize();
                m_SceneControl.Scene.TrackingLayer.Clear();
                m_SceneControl.Scene.Refresh();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public void Analyst()
        {
            var lineWS2d = this.m_SceneControl.Scene.Workspace.Datasources["WS"].Datasets["WSLINE"];
            var lineYS2d = this.m_SceneControl.Scene.Workspace.Datasources["YS"].Datasets["YSLINE"];
            //var point2ds = new Point2Ds(new List<Point2D> { m_StartPoint, m_EndPoint }.ToArray());
            if (m_TheLine == null) return;
            var p1 = m_TheLine[0][0];
            var p2 = m_TheLine[0][1];
            var point2ds = new Point2Ds(new List<Point2D> { new Point2D(p1.X, p1.Y), new Point2D(p2.X, p2.Y) }.ToArray());

            double kOfLine;
            if (p1.X == p2.X)
            {
                kOfLine = 0.0;
            }
            else
            {
                kOfLine = (p1.Y - p2.Y) / (p1.X - p2.X);
            }
            bool westToEast;
            if (Math.Abs(kOfLine) > 1)
            {
                westToEast = false;
            }
            else
            {
                westToEast = true;
            }
            var lineDrawed = new GeoLine(point2ds);
            QueryParameter parameter = new QueryParameter
            {
                SpatialQueryObject = lineDrawed,
                SpatialQueryMode = SpatialQueryMode.Cross,
                HasGeometry = true
            };
            DatasetVector datasetWS = lineWS2d as DatasetVector;
            DatasetVector datasetYS = lineYS2d as DatasetVector;
            Recordset recordsetWS = datasetWS.Query(parameter);
            Recordset recordsetYS = datasetYS.Query(parameter);

            var dt1 = ToDataTable(recordsetWS, "污水管线");
            var dt2 = ToDataTable(recordsetYS, "雨水管线");
            dt1.Columns.Add("图层").SetOrdinal(0);
            foreach (DataRow dr in dt1.Rows)
            {
                dr[0] = "污水管线";
            }
            dt2.Columns.Add("图层").SetOrdinal(0);
            foreach (DataRow dr in dt2.Rows)
            {
                dr[0] = "雨水管线";
            }
            dt1.Merge(dt2);
            var b1 = recordsetWS.Bounds;
            var b2 = recordsetYS.Bounds;
            if (b1.Width > 0 && b2.Width > 0 && b1.Height > 0 && b2.Height > 0)
            {
                b1.Union(b2);
            }
            if (b1.Width > 0 && b1.Height > 0)
            {
                this.m_SceneControl.Scene.EnsureVisible(b1, 0);
            }
            else if (b2.Width > 0 && b2.Height > 0)
            {
                this.m_SceneControl.Scene.EnsureVisible(b2, 0);
            }
            var lookAt = this.m_SceneControl.Scene.LookAt;
            if (!double.IsNaN(lookAt.Longitude))
            {
                LookAt la = new LookAt()
                {
                    Longitude = m_TheLine.InnerPoint3D.X,
                    Latitude = m_TheLine.InnerPoint3D.Y,
                    Tilt = 85,
                    Range = 50,
                    Heading = Math.Atan(Math.Abs((p1.Y - p2.Y) / (p1.X - p2.X))) / (Math.PI / 180),
                    Altitude = m_TheLine.InnerPoint3D.Z + 10
                };
                if (la.IsValid)
                {
                    this.m_SceneControl.Scene.LookAt = la;
                }
                else
                {
                    Sunny.UI.UIMessageBox.ShowWarning("绘制的剖面位置不正确，请重新绘制。");
                    return;
                }
            }
            var wF = new Sunny.UI.UIWaitForm();
            wF.Show();
            Task.Factory.StartNew(() =>
            {
                System.Threading.Thread.Sleep(2000);
            }).ContinueWith((t) =>
            {
                wF.Close();
                List<double> xPositionsWS = new List<double>();
                List<double> yDeepsWS = new List<double>();
                List<double> rWS = new List<double>();
                GetValues(westToEast, recordsetWS, ref xPositionsWS, ref yDeepsWS, ref rWS);

                List<double> xPositionsYS = new List<double>();
                List<double> yDeepsYS = new List<double>();
                List<double> rYS = new List<double>();
                GetValues(westToEast, recordsetYS, ref xPositionsYS, ref yDeepsYS, ref rYS);
                var bitMap = this.m_SceneControl.Scene.OutputSceneToBitmap(false);
                ProfileAnalystFormNew pa = new ProfileAnalystFormNew
                {
                    Bitmap = bitMap,
                    WestToEast = westToEast
                };
                if (westToEast)
                {
                    pa.LineMax = p1.X > p2.X ? p1.X : p2.X;
                    pa.LineMin = p1.X < p2.X ? p1.X : p2.X;
                }
                else
                {
                    pa.LineMax = p1.Y > p2.Y ? p1.Y : p2.Y;
                    pa.LineMin = p1.Y < p2.Y ? p1.Y : p2.Y;
                }
                pa.Positions.Add(xPositionsWS);
                pa.Positions.Add(xPositionsYS);
                pa.Depths.Add(yDeepsWS);
                pa.Depths.Add(yDeepsYS);
                pa.Radiuses.Add(rWS);
                pa.Radiuses.Add(rYS);
                pa.SetDataTable(dt1);
                pa.Show();
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }
        public DataTable ToDataTable(Recordset recordset, string layerName)
        {
            DataTable dt = new DataTable(layerName);
            try
            {
                FieldInfos fieldInfos = recordset.GetFieldInfos();
                // 输出字段名
                // Output the field name
                int count = fieldInfos.Count;
                for (int i = 0; i < count; i++)
                {
                    string fieldname = fieldInfos[i].Name;
                    if (fieldname.ToUpper().StartsWith("SS")) continue;
                    if (fieldname.ToUpper().StartsWith("SM")) continue;
                    dt.Columns.Add(fieldname);
                    dt.Columns[dt.Columns.Count - 1].Caption = fieldInfos[i].Caption;
                }
                // 输出字段值
                // Output the field value
                recordset.MoveFirst();
                int length = recordset.RecordCount;
                for (int i = 0; i < length; i++)
                {
                    DataRow dr = dt.NewRow();
                    var actIndex = 0;
                    for (int j = 0; j < count; j++)
                    {
                        var fieldname = fieldInfos[j].Name;
                        if (fieldname.ToUpper().StartsWith("SS")) continue;
                        if (fieldname.ToUpper().StartsWith("SM")) continue;
                        var objValue = recordset.GetFieldValue(j);
                        string value = objValue?.ToString();
                        dr[actIndex++] = value;
                    }
                    dt.Rows.Add(dr);
                    Console.WriteLine();
                    recordset.MoveNext();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return dt;
        }
        private void GetValues(bool westToEast, Recordset recordset, ref List<double> xPositions, ref List<double> yDeeps, ref List<double> radiuses)
        {
            recordset.MoveFirst();
            for (int i = 0; i < recordset.RecordCount; i++)
            {
                var we = recordset.GetGeometry().InnerPoint.X;
                var ns = recordset.GetGeometry().InnerPoint.Y;
                if (westToEast)
                {
                    xPositions.Add(we);
                }
                else
                {
                    xPositions.Add(ns);
                }
                var deepStart = recordset.GetDouble("SSStart_Depth");
                var deepEnd = recordset.GetDouble("SSEnd_Depth");
                var radius = recordset.GetDouble("管径");
                yDeeps.Add((deepStart + deepEnd) / 2);
                radiuses.Add(radius);
                recordset.MoveNext();
            }
        }


    }
}
